/*
 * @Author: Jiraiya
 * @Date: 2020-05-07 14:33:57
 * @LastEditors: Jiraiya
 * @LastEditTime: 2020-05-08 15:52:36
 * @Description: 
 */

const fs = require('fs');

const path = require('path');

const Service = require('../base/Service');

const pathConfig = bee.getSystemConfig('cms_config');

const cmsMapping = bee.getSystemConfig('cms_mapping');

const {utils, logger} = bee;


const redisClient = null;

//key值
const CMS_DATA_CACHE_REDIS_KEY_PERFIX = 'node:cms:common:redis';

class cmsManager extends Service{

    constructor(ctx) {
        super(ctx);

        this.backendName = 'cms';
        this.backend = {
            host : '127.0.0.1',
            port : 8080
        };
    }

    /**
     *
     * @param key
     * @param isPreview
     * @returns {Promise}
     */
    getArticleByName( key, isPreview ){

        isPreview = isPreview === true;

        let fileId = this.getCMSIdByName( key );

        return this.requestCMS( fileId, 'article', isPreview );
    }

    /**
     * data数据
     * @param key
     * @param isPreview
     * @returns {Promise}
     */
    getDataByName( key, isPreview ){

        isPreview = isPreview === true;

        let fileId = this.getCMSIdByName( key );

        return this.requestCMS( fileId,'data', isPreview );
    }

    /**
     * page builder数据
     * @param key
     * @param isPreview
     * @returns {Promise}
     */
    getPageByName( key, isPreview ){

        isPreview = isPreview === true;

        let fileId = this.getCMSIdByName( key );

        return this.requestCMS( fileId,'page', isPreview );
    }

    //读取cms发布的文件
    async requestCMS( docId, type, isPreview = false ){

        //校验 ObjectId 合法性
        if( ! /^[0-9a-fA-F]{24}$/.test(docId) ){
            return {
                status: '-1',
                message: 'cmsId不合法'
            };
        }

        //文档绝对路径
        let DEV_CMS_File_DIR = "";

        switch(type){
            case 'data':
                DEV_CMS_File_DIR =  isPreview ? pathConfig["data_preview_dir"] : pathConfig["data_dir"];
                break;
            case 'article':
                DEV_CMS_File_DIR =  isPreview ? pathConfig["article_preview_dir"] : pathConfig["article_dir"];
                break;
            case 'page':
                DEV_CMS_File_DIR =  isPreview ? pathConfig["page_preview_dir"] : pathConfig["page_dir"];
                break;
            default:
                return {
                    status: '-1',
                    message: 'type不合法'
                }
                break;
        }

        //直接通过ID读取
        DEV_CMS_File_DIR = path.join( DEV_CMS_File_DIR , docId + '.json' );

        logger.debug(`读取cms文档${DEV_CMS_File_DIR}，文档类型为${type}`);

        //本地开发时，通过173机器上的服务，读取线下cms文档
        if( utils.getNodeEnv() === 'development' ){
            return super.curl('/getCMSData', {
                data: {
                    docId : docId,
                    type : type
                }
            });
        }

        return new Promise( function( resolve, reject ){
            fs.readFile( DEV_CMS_File_DIR, function(err, data){
                if( err ){
                    return reject( err );
                }

                try{
                    data = JSON.parse( data );
                }catch(e){
                    return reject(e);
                }

                resolve( data );
            });
        } ).then((data)=>{
            return {
                status: 0,
                message: 'success',
                data
            }
        }).catch((err)=>{
            logger.warn({
                msg: `read cms file error`,
                extra: `docId=${docId}`,
                err: err,
            });
            return {
                status: -1,
                message: '读取文档出错：',
            }
        })

    }

    /**
     * 通过文档名来获取文档的id值
     * @param docName
     * @returns {string}
     */
    getCMSIdByName(docName){

        let finalFileName = '';

        //获取CMS文件对应的文档id
        let fileNameArr = docName.split("."),
            fileNameArrLen = fileNameArr.length,
            count = 0,
            fileNameTemp = cmsMapping;

        while( count < fileNameArrLen ){
            let key = fileNameArr[ count ];
            fileNameTemp = fileNameTemp[ key ];
            if( ! fileNameTemp ){
                break;
            }
            if( count === fileNameArrLen - 1 ){
                finalFileName = fileNameTemp;
            }
            count++;
        }

        return finalFileName;
    }


    /**
     * 通过配置名，从redis中读取cms文档
     * @param extraOptions
     * @param type
     * @param docName 文档id的配置名
     */
    getCmsDataInRedisByName(docName ,type){

        let docId = this.getCMSIdByName( docName );

        return this.requestDocFromRedis( docId ,type );
    }

    /**
     * 通过文档id，从redis中获取cms文档
     * @param extraOptions
     * @param type
     * @param docId 文档id
     * @param preview
     * @param local
     * @returns {*}
     */
    getCmsDataInRedis(docId ,type){
        return this.requestDocFromRedis( docId ,type );
    }

    /**
     * 从redis中获取cms文档数据
     * @param docId
     * @param type
     */
    async requestDocFromRedis(docId,type){

        const { ctx } = this;

        if(docId && type){
            let redisKey = `${CMS_DATA_CACHE_REDIS_KEY_PERFIX}:${type}:${docId}`;

            try{
                let value = await ctx.app.redis.get(redisKey);
                if(value) {
                    value = JSON.parse(value);

                    return Promise.resolve({
                        status: 0,
                        message: 'OK',
                        data: value
                    });
                }
            }catch(e){
                logger.warn({
                    msg: `read cms cache in redis error type:${type},docId:${docId}`,
                    err: e,
                });
            }

            logger.warn({
                msg: `read cms redis cache fail fall back to file`,
                extra: `type:${type},docId:${docId}`
            });

            //如果redis中读取不到数据，就走文件读取
            return this.requestCMS( docId, type);
        }else{
            return Promise.reject({
                status: -1,
                message: '缺少参数或者参数错误'
            })
        }
    }
}

module.exports = cmsManager;
